package steampunk.geom;

public abstract class BaseGeom implements Geom {

	private volatile double x = 0;
	private volatile double y = 0;
	private volatile double lx = 0;
	private volatile double ly = 0;
	private volatile double vx = 0;
	private volatile double vy = 0;
	private volatile double lvx = 0;
	private volatile double lvy = 0;
	
	private void setLasts() {
		this.lx = this.x;
		this.ly = this.y;
		this.lvx = this.vx;
		this.lvy = this.vy;
	}
	
	public double lastVelX() {
		return lvx;
	}
	public double lastVelY() {
		return lvy;
	}
	
	public void centerX(double x) {
		setX(getX() - centerX() + y);
	}
	
	public void centerY(double y) {
		setY(getY() - centerY() + y);
	}
	
	public double centerX() {
		return (left() + right()) / 2;
	}
	
	public double centerY() {
		return (top() + bottom()) / 2;
	}
	
	public double dx() {
		return x - lx;
	}
	public double dy() {
		return y - ly;
	}
	
	public double getWidth() {
		return right() - left();
	}
	public double getHeight() {
		return bottom() - top();
	}
	
	public double getVelX() {
		return vx;
	}
	public double getVelY() {
		return vy;
	}
	public void setVelX(double d) {
		this.vx = d;
	}
	public void setVelY(double d) {
		this.vy = d;
	}
	
	private double deci(double i, double amount) {
		if (i > 0) {
			if (i - amount <= 0)
				return 0;
			return i - amount;
		} else {
			if (i + amount >= 0)
				return 0;
			return i + amount;
		}
	}
	
	public void decelerate(double x, double y) {
		vx = deci(vx, x);
		vy = deci(vy, y);
	}
	public void accelerate(double x, double y) {
		this.vx += x;
		this.vy += y;
	}
	public void setVelocity(double x, double y) {
		this.vx = x;
		this.vy = y;
		this.lvx = vx;
		this.lvy = vy;
	}
	
	public void hardSetX(double x) {
		this.x = x;
		this.lx = x;
	}
	
	public void hardSetY(double y) {
		this.y = y;
		this.ly = y;
	}
	
	public void setX(double x) {
		this.x = x;
	}
	public void setY(double y) {
		this.y = y;
	}
	public void modX(double x) {
		this.x += x;
	}
	public void modY(double y) {
		this.y += y;
	}
	public double getX() {
		return x;
	}
	public double getY() {
		return y;
	}
	
	public int ix() {
		return (int)x;
	}
	public int iy() {
		return (int)y;
	}
	
	public double lastX() {
		return lx;
	}
	public double lastY() {
		return ly;
	}
	
	public void moveBy(double x, double y) {
		this.x += x;
		this.y += y;
	}
	public void moveTo(double x, double y) {
		this.x = x;
		this.y = y;
		this.lx = x;
		this.ly = y;
	}
	
	public void updatePosition(double seconds) {
		setLasts();
		x += vx * seconds;
		y += vy * seconds;
	}
	
	public void update(double seconds) {
		updatePosition(seconds);
	}
	
	
	/**
	 * Returns the last position of the bottom (this
	 * may break if the height changed between now
	 * and the last frame)
	 * @return
	 */
	public double lastBottom() {
		return (bottom()-getY()) + lastY();
	}
	
	/**
	 * Returns the last position of the top (this
	 * may break if the height changed between now
	 * and the last frame)
	 * @return
	 */
	public double lastTop() {
		return (top()-getY()) + lastY();
	}
	
	/**
	 * Returns the last position of the left edge (this
	 * may break if the width changed between now and
	 * the last frame)
	 * @return
	 */
	public double lastLeft() {
		return (left()-getX()) + lastX();
	}
	
	/**
	 * Returns the last position of the right edge (this
	 * may break if the width changed between now and the
	 * last frame)
	 * @return
	 */
	public double lastRight() {
		return (right()-getX()) + lastX();
	}
}
